#!/home/wcaarls/compile/bin/python

import time, sys, lockdict, math, random, thread

def await(results):
  done = False
  while not done:
    done = True
    results.lock()
    for i in results.itervalues():
      if len(i) == 0:
        done = False
        break
    results.unlock()
    if not done:
      print "p"
      time.sleep(0.1)
      print "b"

def collapse(r):
  # If result is out of bounds, guide it back
  if r[0] > 0.1 or r[1] > 100 or r[2] > 0.1:
    return 1000 + r[0] * 10 + r[1] / 100.0 + r[2] * 10

  return r[0]

def evaluate(createfcn, results):
  global evals

  results2 = lockdict.lockdict()
  createfcn(results2)
  await(results2)
  (s, r) = results2.items()[0]
  
  results.lock()
  results[s] = r
  results.unlock()

  lock.acquire()
  evals = evals + 1
  lock.release()
  
  return (s, r)

def _run(create, variate, output, results, generations, id):
  global threads

  (s, r) = evaluate(create, results)
  
  c = 1
  alpha = 0.995
  
  for i in range(generations):
    (s2, r2) = evaluate(lambda x: variate(s, x), results)
    
    x = collapse(r2[0]) - collapse(r[0])
    
    if x < 0 or math.exp(-x/c) > random.random() or True:
      #print "\r\x1B[" + str(6*id) + "C" + str(i),
    
      s = s2
      r = r2
      
    c = c * alpha
    
  lock.acquire()
  threads = threads - 1
  lock.release()
  
  #print "\r\x1B[" + str(6*id) + "Cdone",
  
def run(create, variate, output, generations=100, iterations=1):
  global threads

  results = lockdict.lockdict()

  threads = iterations

  for i in range(iterations):
    thread.start_new_thread(_run, (create, variate, output, results, generations, i))
    
  while 1:
    lock.acquire()
    #print "\r% Progress: " + "".rjust(evals*40/(generations*iterations), "#"),
    if threads == 0:
      break
    lock.release()
    print "p2"
    time.sleep(0.1)
    print "b2"
    
  print
  for (s, r) in results.iteritems():
    output(s, r)

lock = thread.allocate_lock()
threads = 0
evals = 0
  